#include "lvgl/lvgl.h"
#include "DEV_Config.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

#include <linux/input.h>
#include <fcntl.h>
#include <unistd.h>

// #include "/sensor/ist8310/ist8310_wrapper.h"

#define DISP_BUF_SIZE (240 * 240)

#define ADC_MAX_VALUE 1024
#define ADC_CENTER_VALUE 491
#define ADC_THRESHOLD 80 // 摇杆的死区阈值

void fbdev_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p);

/**
 * A meter with multiple arcs
 */

void lv_show_img(lv_obj_t *img, const lv_img_dsc_t img_dat)
{
    lv_obj_clean(img);
    lv_img_set_src(img, &img_dat);
    lv_obj_center(img);
}

lv_obj_t *cursor;

// 遥感读取函数，将其注册为LVGL的输入设备读取回调
int fd;

void point_adc_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
{

    int x_adc = read_adc_value(ADC_X_PATH);
    int y_adc = read_adc_value(ADC_Y_PATH);
    static int x = 0, y = 0;

    if (x_adc < 0 || y_adc < 0)
    {
        // 读取错误，保持当前位置
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        int move = 0;

        if (x_adc > ADC_CENTER_VALUE + ADC_THRESHOLD)
        {
            x -= 2;
            if (x < 0)
                x = 0;
            move = 1;
        }
        else if (x_adc < ADC_CENTER_VALUE - ADC_THRESHOLD)
        {
            x += 2;
            if (x > 226)
                x = 226;
            move = 1;
        }

        if (y_adc > ADC_CENTER_VALUE + ADC_THRESHOLD)
        {
            y -= 2;
            if (y < 0)
                y = 0;
            move = 1;
        }
        else if (y_adc < ADC_CENTER_VALUE - ADC_THRESHOLD)
        {
            y += 2;
            if (y > 200)
                y = 200;
            move = 1;
        }

        if (move)
        {
            data->point.x = x;
            data->point.y = y;
            // lv_label_set_text_fmt(label3, "%d %d", x, y);
        }

        struct input_event in;
        fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK);

        while (read(fd, &in, sizeof(struct input_event)) > 0)
        {
            if (in.type == EV_KEY)
            {
                if (in.code == 9)
                {
                    if (in.value == 0)
                        data->state = LV_INDEV_STATE_REL;
                    else if (in.value == 1)
                        data->state = LV_INDEV_STATE_PR;
                    // printf("Event: time %ld.%06ld, type %d, code %d, value %d\n",
                    //        in.time.tv_sec, in.time.tv_usec, in.type, in.code, in.value);
                }
                // printf("Event: time %ld.%06ld, type %d, code %d, value %d\n",
                //            in.time.tv_sec, in.time.tv_usec, in.type, in.code, in.value);
                return 0;
            }
        }
    }
}


int encoder_fd;
void encoder_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    struct input_event in;
    fcntl(encoder_fd, F_SETFL, O_ASYNC | O_NONBLOCK);
    while (read(encoder_fd, &in, sizeof(struct input_event)) > 0)
    {
        if (in.type == EV_REL)
        {
            if (in.code == 0)
            {
                // if (in.value == 1)
                // {
                //     // data->state = LV_INDEV_STATE_REL;
                //     encoder_diff+=1;
                //     data->enc_diff=encoder_diff;
                //     printf("%d\n",data->enc_diff);
                // }
                    
                // else if (in.value == -1)
                // {
                //     // data->state = LV_INDEV_STATE_PR;
                //     encoder_diff-=1;
                //     data->enc_diff=encoder_diff;
                //     printf("%d\n",data->enc_diff);
                // }
                // data->state = LV_INDEV_STATE_PRESSED;
                data->enc_diff += in.value;
                // printf("Encoder diff: %d\n", data->enc_diff);
                // printf("Event: time %ld.%06ld, type %d, code %d, value %d\n",\
                //        in.time.tv_sec, in.time.tv_usec, in.type, in.code, in.value);
            }
            // return;
        }

        // struct input_event in2;
        // fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK);
        // while (read(fd, &in2, sizeof(struct input_event)) > 0)
        // {
        //     if (in2.type == EV_KEY)
        //     {
        //         if (in2.code == 3)
        //         {
        //             if (in2.value == 0)
        //                 data->state = LV_INDEV_STATE_REL;
        //             else if (in2.value == 1)
        //                 data->state = LV_INDEV_STATE_PR;
                    
        //         }
        //         printf("Event: time %ld.%06ld, type %d, code %d, value %d\n",
        //                    in2.time.tv_sec, in2.time.tv_usec, in2.type, in2.code, in2.value);
        //     }
        // }
    }
}

// 定义输入事件类型
#define EV_TYPE_SOUND EV_SND
// 定义声音类型和事件代码
#define SND_TYPE_BEEP SND_BELL
#define DEVICE_PATH "/dev/input/event0"

// 打开设备
int open_device()
{
    int fd = open(DEVICE_PATH, O_WRONLY);
    if (fd == -1)
    {
        perror("Failed to open device");
    }
    return fd;
}

// 关闭设备
void close_device(int fd)
{
    close(fd);
}

// 发送蜂鸣器控制事件
void control_beeper(int fd, int frequency, int duration_ms)
{
    struct input_event event;
    memset(&event, 0, sizeof(event));

    // 填充输入事件
    event.type = EV_TYPE_SOUND;
    event.code = SND_TYPE_BEEP;
    event.value = frequency; // 频率控制
    event.time.tv_sec = 0;
    // event.time.tv_usec = duration_ms * 1000; // 持续时间控制

    // 发送输入事件
    if (write(fd, &event, sizeof(event)) < sizeof(event))
    {
        perror("Failed to write event");
    }
}

lv_indev_t *encoder_indev;

int main(void)
{
    /*LittlevGL init*/
    lv_init();

    /*Linux frame buffer device init*/
    fbdev_init();

    // 输入设备测试


    DEV_ModuleInit();
    LED_write("gpio4/value", "1");

    /*A small buffer for LittlevGL to draw the screen's content*/
    static lv_color_t buf[DISP_BUF_SIZE];

    /*Initialize a descriptor for the buffer*/
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    /*Initialize and register a display driver*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &disp_buf;
    disp_drv.flush_cb = fbdev_flush;
    disp_drv.hor_res = 240;
    disp_drv.ver_res = 240;
    lv_disp_drv_register(&disp_drv);

    // 初始化并注册输入设备驱动
    const char *device = "/dev/input/event3"; // 根据实际设备路径修改
    fd = open(device, O_RDONLY);
    if (fd == -1)
    {
        perror("Failed to open device");
        return 1;
    }

    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = point_adc_read; // 使用ADC读取函数
    lv_indev_t *adc_indev = lv_indev_drv_register(&indev_drv);
    cursor = lv_img_create(lv_scr_act());
    lv_img_set_src(cursor, LV_SYMBOL_GPS);
    lv_indev_set_cursor(adc_indev, cursor);
    /////////////////////////

    //注册编码器
    const char *encoder_device = "/dev/input/event1"; // 根据实际设备路径修改
    encoder_fd = open(encoder_device, O_RDONLY);
    if (encoder_fd == -1)
    {
        perror("Failed to open device");
        return 1;
    }

    static lv_indev_drv_t indev_drv_encoder;
    lv_indev_drv_init(&indev_drv_encoder);
    indev_drv_encoder.type = LV_INDEV_TYPE_ENCODER; //指定设备类型
    indev_drv_encoder.read_cb = encoder_read; // 指定回调函数
    encoder_indev = lv_indev_drv_register(&indev_drv_encoder); //注册驱动
    ///////////

    // 震动
    int beep_fd = open_device();
    if (beep_fd == -1)
    {
        return 1;
    }
    // 震动持续200毫秒
    control_beeper(beep_fd, 1000, 100);
    sleep(1);
    control_beeper(beep_fd, 0, 0);
    close_device(beep_fd);

    // 初始化UI
    ui_init();

    LED_write("gpio4/value", "0");

    /*Handle LitlevGL tasks (tickless mode)*/
    while (1)
    {
        lv_timer_handler();
        usleep(5000);
    }

    return 0;
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if (start_ms == 0)
    {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}
